// let:

// {
  // let a=1;
  // var b=0;
  // console.log(a);
// }
// console.log(b);
// console.log(a);//let 声明的变量只在该代码块里面有效
// window.onload=function (ev) {
//   let a=1;
//   var b=0;
//   console.log(a);
// };
// console.log(b);//函数和代码块原来是不一样的，代码块里面的能拿到，函数作用域里面的不能拿到

// for循环使用let:
// for(let i=0;i<5;i++){
//   console.log(i)
// }
// console.log(i)//把for循环也看成一个代码块，let声明的在代码块外无效；
//
// var arr=[];
// for(var i=0;i<10;i++){
//   arr[i]=function () {
//     return i
//   }
// }
// console.log(arr[6]());
// console.log(i);
//
// var arr=[];
// for(let i=0;i<10;i++){
//   arr[i]=function () {
//     return i
//   }
// }
// console.log(arr[6]());
//
// for(let i=0;i<10;i++){
//   let i="kl";
//   console.log(i)//循环变量部分是父作用域，循环体内部是子作用域
// }
//
// for(var i=0;i<10;i++){
//   var i="kl";
//   console.log(i)//循环变量部分是父作用域，循环体内部是子作用域
// }

//不存在变量提升：
// var声明的可以变量提升，只是未定义，而let声明的不能变量提升，直接报错
// {
//   var a="jk";
//   let a=1;
//   //同一个作用域不能同时用let和var声明同一个变量。
//   // 也不能同时用一个以上let声明同一个变量，var可以。
//   console.log(a);
//
// }

// 暂时性死区
// {
//   var tmp = 123;
//   if (true) {
//     tmp = 'abc'; // ReferenceError
//     let tmp;
//     console.log(tmp);// ReferenceError
//    //  只要块级作用域内存在let命令，
//    //  它所声明的变量就“绑定”（binding）这个区域，不再受外部的影响。
//    // 因此不能在函数传了参数的情况下在该作用域再用let声明该参数；
//    function fun(tmp){
//     let tmp="jk"//报错
//     {
//      let tmp="jj"//不报错；
//     }
//    }
//   }
// }
// {
//   var b="dd";
//   if(true){
//     b="kk";
//     console.log(b);
//     var b="jh"
//   }
// }
// var tmp = new Date();
// function f() {
//   console.log(tmp);
//   if (true) {
//     var tmp = 'hello world';//会影响父级变量
//   }
// }
// f(); // undefined 变量提升
//
// var tmp = new Date();
// function f() {
//   if (false) {
//     var tmp = 'hello world';//if会影响父级变量
//   }
//   console.log(tmp);
// }
// f(); // undefined 虽然是false未执行，但是也声明了
//
// var tmp = new Date();
// function f() {
//
//   function t() {
//     var tmp = 'hello world';//函数不会影响父级变量
//     return tmp;
//   }
//   console.log(tmp,t());
// }
// f();
//
// function f1() {
//   let n = 5;
//   if (true) {
//     let n = 10;//let实际上为 JavaScript 新增了块级作用域,不会覆盖父级变量值
//   }
//   console.log(n);
// }
// f1(); // 5

{
  function bar(x = y, y = 2) {
    return [x, y];
  }
  
  bar(); // 报错
  
  function bar(x = 2, y = x) {
    return [x, y];
  }
  bar(); // [2, 2]
}
//这里没懂，先写x=2就是声明了，前面那个没声明

// function f() { console.log('I am outside!'); }
// let a=1;
// (function () {
//   if (true) {
//     // 重复声明一次函数f
//     function f() { console.log('I am inside!'); }
//     let a=3;
//     console.log(a)
//   }
//   f();//为什么拿不到外面的f() 因为if里面声明了，但是是false又执行不了;
//   console.log(a)
// }());

// const :
//1、 const 声明的是一个常量，不可重新声明，一旦声明就必须赋值。
// const a=1;
// const b;//未赋值，报错

// 2、与let一样，只在块级作用域内有效,变量不提升
// {
//   console.log(aa);//不提升，报错
//   const aa="hjh"
//   console.log(aa);
//   console.log(a);
// }
// console.log(aa);//拿不到aa

// 3、const与let一样，不可重复声明，let声明了就不能用const声明，const声明了就不能用let声明。

// 4、const声明的是一个常量，指的是内存地址不能改变，但是地址里面的内容可以变，如数组和对象
//   const obj={
//     kk:"jggj",
//     jf:"jhhjk",
//     name:"anla"
//   }
//   const obj1=obj;
// obj1.jk="sdfgs";
// console.log(obj1);

// const foo = Object.freeze({});//Object.freeze()阻止修改对象，阻止添加新属性
// console.log(foo);

// 函数里面的this，如果函数不是作为对象的方法运行，而是单纯作为函数运行，this会指向顶层对象。

// var getGlobal = function () {
//   if (typeof self !== 'undefined') { return self; }
//   if (typeof window !== 'undefined') { return window; }
//   if (typeof global !== 'undefined') { return global; }
//   throw new Error('unable to locate global object');
//   return this
// };
// console.log(getGlobal());
